﻿using System;
using System.Collections.Generic;
using System.Data;
using System.IO;
using System.Linq;
using System.Text;

namespace XExcel
{
    /// <summary>
    /// CSV文件类写入器,将指定的表格写入到CSV
    /// </summary>
    public static class CsvWriter
    {
        /// <summary>
        /// 转换成行
        /// </summary>
        /// <returns></returns>
        public static IEnumerable<string> ConvertToLines(DataTable table, bool withHeader = true, char separator = ',')
        {
            if(table == null)
            {
                throw new ArgumentNullException(nameof(table));
            }
            CsvHelper.CheckSeparator(separator);

            var columns = table.Columns.OfType<DataColumn>().Select(x => x.ColumnName).ToList();
            var sepStr = separator.ToString();
            if(withHeader)
            {
                var headers = string.Join(sepStr, columns.Select(x => FormatCell(x, separator)));
                yield return headers;
            }

            foreach(DataRow row in table.Rows)
            {
                var rowstr = string.Join(sepStr, row.ItemArray.Select(x => FormatCell(x, separator)));
                yield return rowstr;
            }
        }

        private static string FormatCell(object value, char separator)
        {
            if(value == null || value == DBNull.Value)
            {
                return "";
            }
            var str = value.ToString();
            var needQuote = false;
            if(str.Contains(separator) || str.Contains('\"') || str.Contains('\r') || str.Contains('\n'))
            {
                needQuote = true;
            }
            if(needQuote)
            {
                str = str.Replace("\"", "\"\"");
                str = "\"" + str + "\"";
            }
            return str;
        }
        /// <summary>
        /// 写入文件
        /// </summary>
        /// <param name="filePath">文件路径</param>
        /// <param name="encoding">编码格式</param>
        public static void Write(string filePath, Encoding encoding, DataTable table, bool withHeader = true, char separator = ',')
        {
            using(var sw = new StreamWriter(filePath, false, encoding))
            {
                Write(sw, table, withHeader, separator);
                sw.Close();
            }
        }
        /// <summary>
        /// 写入到流写入器
        /// </summary>
        /// <param name="writer"></param>
        public static void Write(StreamWriter writer, DataTable table, bool withHeader = true, char separator = ',')
        {
            if(writer == null)
            {
                throw new ArgumentNullException(nameof(writer));
            }
            var lines = ConvertToLines(table, withHeader, separator);
            foreach(var line in lines)
            {
                writer.WriteLine(line);
            }
            writer.Flush();
        }

        /// <summary>
        /// 写入流
        /// </summary>
        /// <returns></returns>
        public static MemoryStream Write(DataTable table, bool withHeader = true, char separator = ',')
        {
            using(var ms = new MemoryStream())
            {
                using(var sw = new StreamWriter(ms))
                {
                    Write(sw, table, withHeader, separator);
                    sw.Close();
                }
                return ms;
            }
        }
    }
}